home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Applications
/
Fixation 1.3
/
game.cpp
< prev
next >
Wrap
Text File
|
1996-04-11
|
42KB
|
1,720 lines
// game.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mytypes.h"
#include "error.h"
#include "globals.h"
#include "menus.h"
#include "window.h"
#include "main.h"
#include "util.h"
#include "preffile.h"
#include "connexions.h"
#include "fastmap.h"
#include "graphics.h"
#include "game.h"
#include "incoming.h"
#include "outgoing.h"
#define optionkey 0x3A
unsigned char km[16];
Game *gGames = nil;
enum {
kNoMove = 0,
kMove,
kBugMove,
kSetupMove
};
Game *gDragGame = nil;
short gClickType = kNoMove, gOldPiece;
Point gOrigPoint, gDestPoint;
static Rect dirty = {0,0,0,0};
static short offx, offy;
Board initialPosition = { // this is actually wrong, but it never really gets used . . .
{ WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
{ WhitePawn, WhitePawn, WhitePawn, WhitePawn,
WhitePawn, WhitePawn, WhitePawn, WhitePawn },
{ empty, empty, empty, empty,
empty, empty, empty, empty },
{ empty, empty, empty, empty,
empty, empty, empty, empty },
{ empty, empty, empty, empty,
empty, empty, empty, empty },
{ empty, empty, empty, empty,
empty, empty, empty, empty },
{ BlackPawn, BlackPawn, BlackPawn, BlackPawn,
BlackPawn, BlackPawn, BlackPawn, BlackPawn },
{ BlackRook, BlackKnight, BlackBishop, BlackQueen,
BlackKing, BlackBishop, BlackKnight, BlackRook }
};
static short
Piece2Player(short pc)
{
if (!pc)
return -1;
else if (pc <= WhiteKing)
return kWhite;
else
return kBlack;
}
void
InitGame(void)
{
gPlaying = false;
curTime = TickCount();
LoadAllGraphics();
}
void
DrawGameWindow(void)
{
// SetGWorld(gameWindow, maindev);
// CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(gameWindow->portPixMap),
// &screenRect, &screenRect, srcCopy, nil);
}
void
DisposeGame(Game *game)
{
if (game->isFirst)
gPrefs.gameWindPos1 = GetWindowRect((WindowPtr) game->wind);
if (game->isSecond)
gPrefs.gameWindPos2 = GetWindowRect((WindowPtr) game->wind);
DisposeWindow((WindowPtr) game->wind);
DisposPtr((Ptr) game);
}
#if TIMESTAMP
void init_encrypt();
void init_process_chars_from_server(void);
void send_alarm(void);
#include "timeseal.h"
#endif
void
StartPlaying(void)
{
#if TIMESTAMP
if (gPrefs.serverType == kIcc && gPrefs.timeseal) {
init_encrypt();
init_process_chars_from_server();
}
if (gPrefs.serverType == kFics && gPrefs.timeseal) {
InitTimeseal();
}
gSentAlarm = false;
#endif
gPlaying = true;
gSetStyle = false;
gNeedPassword = true;
gCaughtPrompt = false;
gWillSetup = false;
gLookinAtStorage = false;
gCheckingVersion = 0;
strcpy(gPrompt, "fics% ");
if (gPrefs.serverType == kIcc) {
gPrompt[0] = 'a';
gCaughtPrompt = true;
}
}
void
StopPlaying(void)
{
if (gPlaying) {
gPlaying = false;
// clean up all games
Game *game = gGames, *nx;
while (game) {
nx = game->next;
DisposeGame(game);
game = nx;
}
gGames = nil;
}
}
Game *
FindGameFromWindow(WindowPtr win)
{
Game *game = gGames;
while (game) {
if (game->wind == (CWindowPtr) win)
return game;
game = game->next;
}
return nil;
}
void
DoFlip(void)
{
Game *game = FindGameFromWindow(FrontWindow());
if (!game)
return;
game->flip = !game->flip;
DrawGame(game);
}
void
DoEscapeKey(void)
{
if (gClickType == kNoMove)
return;
if (gClickType == kMove || gClickType == kSetupMove)
gDragGame->board[gOrigPoint.h][gOrigPoint.v] = gOldPiece;
gDragGame->tempDest.h = -1;
DrawGameBoard(gDragGame);
gClickType = kNoMove;
ShowCursor();
}
void
CloseGameWindow(WindowPtr win)
{
Game *game = FindGameFromWindow(win);
if (game) {
// check to see if we're dragging here
if (game == gDragGame && gClickType != kNoMove) {
gClickType = kNoMove;
ShowCursor();
}
if (gGames == game)
gGames = game->next;
if (game->next)
game->next->prev = game->prev;
if (game->prev)
game->prev->next = game->next;
// let's tell the server if we're meant to
if (gPrefs.smartClose && game->jexiste && game->number > 0) {
if (game->relation == RELATION_OBSERVING_PLAYED)
bprintf("unobserve %d\n", game->number);
else if (game->relation == RELATION_EXAMINING)
bprintf("unexamine\n");
}
DisposeGame(game);
}
}
void
SetGameWindowSize(Game *game, short delta)
{
short newh, newv;
CWindowPtr win = game->wind;
SetGWorld(win, maindev);
newh = win->portRect.right + delta;
newv = win->portRect.bottom + delta;
SizeWindow((WindowPtr) win, newh, newv, false);
InvalRect(&win->portRect);
game->p2OffsetY += delta;
game->boardRect.right += delta;
game->boardRect.bottom += delta;
game->sqsize = game->boardRect.right / 8;
if (game->isFirst)
gPrefs.boardSize1 = game->boardRect.right;
if (game->isSecond)
gPrefs.boardSize2 = game->boardRect.right;
// move buttons
short nnn;
for (nnn=0; nnn<kNumGameControls; nnn++)
if (game->ctl[nnn])
MoveControl(game->ctl[nnn], (**game->ctl[nnn]).contrlRect.left,
(**game->ctl[nnn]).contrlRect.top + delta);
}
void
GrowGameWindow(CWindowPtr win, Point pt)
{
Game *game = FindGameFromWindow((WindowPtr) win);
if (!game)
return;
Rect sr = { kWinHeight - kSquareSize * 4, kSquareSize * 4, kWinHeight + kSquareSize * 56, kSquareSize * 64 };
if (game->footer) OffsetRect(&sr, 0, kFooterSize);
if (game->bug || game->setup) OffsetRect(&sr, kBugspace, 0);
short oldh, oldv, dh, dv, newh, newv;
SetPort((WindowPtr) win);
// remember current size
oldh = win->portRect.right; oldv = win->portRect.bottom;
// do the green thumb shit
long ret = GrowWindow((WindowPtr) win, pt, &sr);
if (!ret) // no grow
return;
newh = LoWord(ret); newv = HiWord(ret);
dh = newh - oldh; dv = newv - oldv;
// must keep square -- pick shortest
short delta = dh;
if (dv < dh) delta = dv;
delta -= delta % 8; // keep aligned
if (delta == 0)
return;
SetGameWindowSize(game, delta);
}
static Fastmap *
Piece2Fastmap(short pc)
{
if (!pc)
return nil;
short offs = gPrefs.pieceSet * 2;
if (pc <= WhiteKing)
return bpix[Bwhite+offs][pc-1];
if (pc <= BlackKing)
return bpix[Bblack+offs][pc-WhiteKing-1];
return nil;
}
static void
DrawMyGrow(Game *game)
{
/* Rect r = {y - 8, x-8, y, x};
FrameRect(&r);
RGBColor col = {0xC000,0xC000,0xC000};
RGBColor ccol = {0x8000,0x8000,0x8000};
RGBForeColor(&col);
PaintRect(&r);
InsetRect(&r, 3, 3);
RGBForeColor(&ccol);
PaintRect(&r);
RGBForeColor(&rgbBlack);
*/
// return;
short x = game->wind->portRect.right;
short y = game->wind->portRect.bottom;
Rect gr = {0, 0, y, x};
gr.left = gr.right - 15;
gr.top = gr.bottom - 15;
ClipRect(&gr);
DrawGrowIcon((WindowPtr) game->wind);
SetRect(&gr, 0, 0, 32000, 32000);
ClipRect(&gr);
}
static void
DrawBoard(Board board, Game *game)
{
short x, y;
Rect r;
Fastmap *fm;
for (x=0;x<8;x++)
for (y=0;y<8;y++) {
if (game->flip)
r.left = (7-x) * kSquareSize;
else
r.left = x * kSquareSize;
r.right = r.left + kSquareSize;
if (game->flip)
r.top = y * kSquareSize;
else
r.top = (7-y) * kSquareSize;
r.bottom = r.top + kSquareSize;
if (!((x + y) & 1))
RGBForeColor(&gPrefs.colBlack);
else
RGBForeColor(&gPrefs.colWhite);
PaintRect(&r);
if (x == game->tempDest.h && y == game->tempDest.v) {
// draw an X where we're trying to go
InsetRect(&r, 4, 4);
RGBColor col = {0xA000, 0, 0};
RGBForeColor(&col);
MoveTo(r.left, r.top);
LineTo(r.right, r.bottom);
MoveTo(r.right, r.top);
LineTo(r.left, r.bottom);
InsetRect(&r, -4, -4);
}
RGBForeColor(&rgbBlack);
fm = Piece2Fastmap(board[x][y]);
if (fm)
fm->DrawMask(boff, &r);
}
}
void
DrawGameBoard(Game *game)
{
SetGWorld(boff, nil);
DrawBoard(game->board, game);
SetGWorld(game->wind, maindev);
Rect r = //boffrect;
//OffsetRect(&r, 0, game->bOffsetY);
game->boardRect;
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&boffrect, &r, srcCopy, nil);
}
static void
DrawStatSet(Game *game, short plr)
{
short len;
char buf[64];
Rect r = boffrect;
r.bottom = kStatY;
RGBColor col = {0xC000,0xC000,0xC000};
RGBColor colW = {0xF000,0xF000,0xF000};
RGBColor colB = {0x5000,0x5000,0x5000};
RGBColor ccol = {0xB000,0x1000,0x1000};
SetGWorld(boff, nil);
TextSize(12);
TextFont(0);
RGBForeColor(&col);
PaintRect(&r);
// draw stuff if we're the current player
if (game->turn == plr && !gPrefs.minimal) {
RGBForeColor(&ccol);
r.bottom = 3;
PaintRect(&r);
r.top = kStatY - 3; r.bottom = kStatY;
PaintRect(&r);
r.top = 0;
}
RGBForeColor(&rgbBlack);
// draw strength
len = sprintf(buf, "%d", game->strength[plr]);
MoveTo(4, 16);
DrawText(buf, 0, len);
// draw a circle if we're the current player
if (game->turn == plr) {
RGBForeColor(&ccol);
short rad = 5;
Rect rec = {kStatY/2 - rad, 27 - rad, kStatY/2 + rad, 27 + rad};
PaintOval(&rec);
RGBForeColor(&rgbBlack);
}
// draw time in a box
// draw time
long tm = game->ptime[plr];
len = sprintf(buf, "%c%d:%02d", tm < 0 ? '-' : ' ',
abs(tm) / 60, abs(tm) % 60);
short plen = TextWidth(buf, 0, len);
Rect rr = {4, 37, 20, 37 + plen + 8};
if (plr == kWhite) {
RGBForeColor(&colW);
PaintRoundRect(&rr, 10, 10);
RGBForeColor(&rgbBlack);
}
else {
RGBForeColor(&colB);
PaintRoundRect(&rr, 10, 10);
RGBForeColor(&colW);
}
MoveTo(rr.left + 4, 16);
DrawText(buf, 0, len);
RGBForeColor(&rgbBlack);
// draw their last move
MoveTo(rr.right + 4, 16);
DrawText(game->lmove[plr], 0, strlen(game->lmove[plr]));
TextSize(10);
TextFont(geneva);
// draw name
Move(4, 0);
DrawText(game->name[plr], 0, strlen(game->name[plr]));
}
/*
static void
DrawStatSet(Game *game, short plr)
{
short len;
char buf[64];
Rect r = boffrect;
r.bottom = kStatY;
RGBColor col = {0xC000,0xC000,0xC000};
RGBColor colW = {0xF000,0xF000,0xF000};
RGBColor colB = {0x5000,0x5000,0x5000};
RGBColor ccol = {0xB000,0x1000,0x1000};
SetGWorld(boff, nil);
RGBForeColor(&col);
PaintRect(&r);
// draw stuff if we're the current player
if (game->turn == plr && !gPrefs.minimal) {
RGBForeColor(&ccol);
r.bottom = 3;
PaintRect(&r);
r.top = kStatY - 3; r.bottom = kStatY;
PaintRect(&r);
r.top = 0;
}
RGBForeColor(&rgbBlack);
// draw name
Rect rr = {4, 37, 20, 37};
if (plr == kWhite) {
rr.right += StringWidth("\pWhite: ") + 2;
RGBForeColor(&colW);
PaintRoundRect(&rr, 10, 10);
RGBForeColor(&rgbBlack);
MoveTo(rr.left + 3, 16);
DrawString("\pWhite: ");
}
else {
rr.right += StringWidth("\pBlack: ") + 2;
RGBForeColor(&colB);
PaintRoundRect(&rr, 10, 10);
RGBForeColor(&colW);
MoveTo(rr.left + 3, 16);
DrawString("\pBlack: ");
RGBForeColor(&rgbBlack);
}
Move(4, 0);
DrawText(game->name[plr], 0, strlen(game->name[plr]));
// draw a circle if we're the current player
if (game->turn == plr) {
RGBForeColor(&ccol);
short rad = 5;
Rect rec = {kStatY/2 - rad, 27 - rad, kStatY/2 + rad, 27 + rad};
PaintOval(&rec);
RGBForeColor(&rgbBlack);
}
len = sprintf(buf, "%d", game->strength[plr]);
MoveTo(4, 16);
DrawText(buf, 0, len);
// draw their last move
MoveTo(192, 16);
DrawText(game->lmove[plr], 0, strlen(game->lmove[plr]));
// draw time
long tm = game->ptime[plr];
len = sprintf(buf, "%c%d:%02d", tm < 0 ? '-' : ' ',
abs(tm) / 60, abs(tm) % 60);
MoveTo(150, 16);
DrawText(buf, 0, len);
}
*/
void
DrawGameStats(Game *game)
{
Rect r = boffrect;
r.bottom = kStatY;
Rect s;
DrawStatSet(game, !game->flip);
MoveTo(0, kStatY-1);
Line(kBoardSize, 0);
MoveTo(0, 0);
Line(kBoardSize, 0);
s = r; OffsetRect(&s, 0, game->p1OffsetY);
SetGWorld(game->wind, maindev);
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&r, &s, srcCopy, nil);
DrawStatSet(game, game->flip);
MoveTo(0, kStatY-1);
Line(kBoardSize, 0);
MoveTo(0, 0);
Line(kBoardSize, 0);
SetGWorld(game->wind, maindev);
// sometimes we have to fit grow box here -- make space for it
if (!game->bug && !game->setup && !game->footer)
if (game->boardRect.right < kBoardSize + 16) {
RGBColor colB = {0x3000,0x3000,0x3000};
RGBForeColor(&colB);
Rect s = r; OffsetRect(&s, 0, game->p2OffsetY);
s.left = kBoardSize - 16; s.right = game->wind->portRect.right;
s.right -= 15;
PaintRect(&s);
s.right += 15;
s.bottom -= 15;
PaintRect(&s);
RGBForeColor(&rgbBlack);
r.right -= 16;
}
s = r; OffsetRect(&s, 0, game->p2OffsetY);
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&r, &s, srcCopy, nil);
}
void
DrawGameHeader(Game *game)
{
Rect r = boffrect;
r.bottom = kHeader;
char buf[32];
short len;
SetGWorld(boff, nil);
RGBColor colB = {0x3000,0x3000,0x3000};
RGBColor colW = {0xE000,0xE000,0xE000};
RGBForeColor(&colB);
PaintRect(&r);
RGBForeColor(&colW);
// MoveTo(0, plr == kWhite ? 0 : kStatY-1);
// Line(kBoardSize, 0);
// PenMode(srcBic);
MoveTo(8, 11);
/* DrawString("\pMove ");
short len = sprintf(buf, "%d", game->officialMove);
DrawText(buf, 0, len); */
len = sprintf(buf, "Mins: %ld Inc: %ld", game->gameMins, game->gameInc);
DrawText(buf, 0, len);
if (game->elapsed[0]) {
Move(8, 0);
DrawText(game->elapsed, 0, strlen(game->elapsed));
}
Move(8, 0);
if (!game->endReason[0]) {
if ((game->relation == RELATION_OBSERVING_PLAYED) ||
(game->relation == RELATION_PLAYING_MYMOVE) ||
(game->relation == RELATION_PLAYING_NOTMYMOVE)) {
len = sprintf(buf, "-> %d:%02d <-", (short) (game->thinking / 60), (short) (game->thinking % 60));
DrawText(buf, 0, len);
}
}
else
DrawText(game->endReason, 0, strlen(game->endReason));
// PenNormal();
RGBForeColor(&rgbBlack);
SetGWorld(game->wind, maindev);
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&r, &r, srcCopy, nil);
}
static void
DrawGameFooter(Game *game)
{
Rect r = boffrect;
r.bottom = kFooterSize;
SetGWorld(boff, nil);
RGBColor colB = {0x3000,0x3000,0x3000};
RGBColor colW = {0xE000,0xE000,0xE000};
RGBForeColor(&colB);
PaintRect(&r);
// RGBForeColor(&colW);
RGBForeColor(&rgbBlack);
SetGWorld(game->wind, maindev);
// sometimes we have to fit grow box here -- make space for it
Rect dest = r;
OffsetRect(&dest, 0, game->p2OffsetY + kStatY);
if (!game->bug && game->boardRect.right < kBoardSize + 16) {
RGBColor colB = {0x3000,0x3000,0x3000};
RGBForeColor(&colB);
Rect s = dest;
s.left = kBoardSize - 16; s.right = game->wind->portRect.right;
s.right -= 15;
PaintRect(&s);
s.right += 15;
s.bottom -= 15;
PaintRect(&s);
RGBForeColor(&rgbBlack);
r.right -= 16;
}
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&r, &dest, srcCopy, nil);
DrawControls((WindowPtr) game->wind);
}
// just copy the pictures in
static void
DrawBugSet(Game *game, short plr)
{
Fastmap *fm, **find;
Rect r = {0, 0, kSquareSize * 5, kSquareSize};
SetGWorld(boff, nil);
RGBForeColor(&bugcol);
PaintRect(&r);
RGBForeColor(&rgbBlack);
// draw pieces
find = bpix[(plr == kWhite ? Bwhite : Bblack) + gPrefs.pieceSet * 2];
short i;
for (i=0;i<5;i++) {
Rect s = {i*kSquareSize, 0, (i+1) * kSquareSize, kSquareSize};
fm = find[i];
fm->DrawMask(boff, &s);
}
}
void
DrawBughouse(Game *game)
{
Rect src = {0, 0, kSquareSize * 5, kSquareSize};
Rect dest = {0, game->boardRect.right + kBugspace - kBugsize,
kBugY, game->boardRect.right + kBugspace};
DrawBugSet(game, !game->flip);
SetGWorld(game->wind, maindev);
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&src, &dest, srcCopy, nil);
DrawBugSet(game, game->flip);
SetGWorld(game->wind, maindev);
OffsetRect(&dest, 0, kBugY + kBugPadding);
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&src, &dest, srcCopy, nil);
// extra stuff
Rect r = {kBugY, game->boardRect.right, kBugY + kBugPadding, game->boardRect.right + kBugspace};
RGBForeColor(&bugcol);
PaintRect(&r);
r.top = kBugY * 2 + kBugPadding; r.bottom = game->wind->portRect.bottom;
PaintRect(&r);
RGBForeColor(&rgbBlack);
MoveTo(game->boardRect.right, 0);
Line(0, game->wind->portRect.bottom);
DrawMyGrow(game);
}
static void
DrawReserveSet(Game *game, short plr)
{
Rect r = {0, 0, kBugY, kBugspace - kBugsize};
SetGWorld(boff, nil);
RGBForeColor(&bugcol);
PaintRect(&r);
RGBForeColor(&rgbBlack);
MoveTo(0, 0);
Line(0, kBugY);
TextSize(12);
TextFont(0);
short nnn;
for (nnn=0;nnn<5;nnn++)
if (game->reserves[plr][nnn]) {
MoveTo(4, nnn * kBugsize + kBugsize / 2 + 6);
DrawChar(game->reserves[plr][nnn] + '0'); // can't be more than 9
}
TextSize(10);
TextFont(geneva);
}
void
DrawReserves(Game *game) // text for numbers of pieces
{
Rect src = {0, 0, kBugY, kBugspace - kBugsize};
Rect dest = {0, game->boardRect.right, kBugY, game->boardRect.right + kBugspace - kBugsize};
DrawReserveSet(game, !game->flip);
SetGWorld(game->wind, maindev);
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&src, &dest, srcCopy, nil);
DrawReserveSet(game, game->flip);
SetGWorld(game->wind, maindev);
OffsetRect(&dest, 0, kBugY + kBugPadding);
CopyBits ((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&src, &dest, srcCopy, nil);
}
void
DrawGame(Game *game)
{
// gworlds should get set automatically
DrawGameBoard(game);
DrawGameStats(game);
DrawGameHeader(game);
if (game->bug) {
DrawReserves(game);
DrawBughouse(game);
}
if (game->footer)
DrawGameFooter(game);
if (game->footer && game->bug) {
// fill in the corner
/* Rect r = game->wind->portRect;
r.left = kBoardSize;
r.top = kWinHeight;
RGBColor colB = {0x3000,0x3000,0x3000};
RGBForeColor(&colB);
PaintRect(&r);
RGBForeColor(&rgbBlack);
*/
}
if (game->boardRect.right > kBoardSize) {
// fill in some grey bits
RGBColor colB = {0x3000,0x3000,0x3000};
RGBForeColor(&colB);
Rect r;
r.right = game->boardRect.right;
r.bottom = game->bOffsetY;
r.top = 0;
r.left = kBoardSize;
PaintRect(&r);
r.bottom = game->wind->portRect.bottom;
r.top = game->boardRect.bottom;
PaintRect(&r);
RGBForeColor(&rgbBlack);
}
// draw grow icon
DrawMyGrow(game);
}
void
DrawGameWindow(WindowPtr win)
{
Game *game = FindGameFromWindow(win);
if (game)
DrawGame(game);
}
void
MakeBughouse(Game *game)
{
if (game->bug)
return;
game->bug = true;
// expand window
short sx = game->boardRect.right + kBugspace, sy = game->wind->portRect.bottom;
SizeWindow((WindowPtr) game->wind, sx, sy, false);
DrawBughouse(game);
}
void
RemoveBughouse(Game *game)
{
if (!game->bug)
return;
game->bug = false;
// shrink window
short sx = game->boardRect.right, sy = game->wind->portRect.bottom;
SizeWindow((WindowPtr) game->wind, sx, sy, false);
SetGWorld(game->wind, maindev);
DrawMyGrow(game);
}
void
MakeFooter(Game *game)
{
if (game->footer)
return;
game->footer = true;
// expand window
short sx = game->wind->portRect.right, sy = game->boardRect.bottom + kStatY + kFooterSize;
SizeWindow((WindowPtr) game->wind, sx, sy, false);
// add controls
Rect bounds = {game->p2OffsetY + kStatY + 2, 24, game->p2OffsetY + kStatY + kFooterSize - 1, 56};
game->ctl[ctlStart] = NewControl((WindowPtr) game->wind, &bounds, "\p|<<",
true, 0, 0, 0, 0, ctlStart); verify(game->ctl[ctlStart]);
OffsetRect(&bounds, 38, 0);
game->ctl[ctlBack] = NewControl((WindowPtr) game->wind, &bounds, "\p<",
true, 0, 0, 0, 0, ctlBack); verify(game->ctl[ctlBack]);
OffsetRect(&bounds, 38, 0);
game->ctl[ctlForward] = NewControl((WindowPtr) game->wind, &bounds, "\p>",
true, 0, 0, 0, 0, ctlForward); verify(game->ctl[ctlForward]);
OffsetRect(&bounds, 38, 0);
game->ctl[ctlEnd] = NewControl((WindowPtr) game->wind, &bounds, "\p>>|",
true, 0, 0, 0, 0, ctlEnd); verify(game->ctl[ctlEnd]);
OffsetRect(&bounds, 44, 0); bounds.right += 20;
game->ctl[ctlRevert] = NewControl((WindowPtr) game->wind, &bounds, "\pRevert",
true, 0, 0, 0, 0, ctlRevert); verify(game->ctl[ctlRevert]);
DrawGameFooter(game);
DrawMyGrow(game);
}
Game *
NewGame(char *p1, char *p2, short gameNum, Boolean flip)
{
Game *game = (Game *) NewPtr(sizeof(Game));
verify(game);
// sticky code to make windows pop up in nice places
game->isFirst = true; game->isSecond = false;
Game *gm = gGames;
while (gm) {
if (gm->isFirst)
game->isFirst = false;
gm = gm->next;
}
if (!game->isFirst) { // well, maybe we can be second then
gm = gGames;
if (gm) {
game->isSecond = true;
while (gm) {
if (gm->isSecond)
game->isSecond = false;
gm = gm->next;
}
}
}
// make window
// now set up game window
gScratch[0] = sprintf((char *) &gScratch[1], "%d: %s vs %s", gameNum, p1, p2);
Rect gameWindowBounds = {40, 4, 40 + kWinHeight, 4 + kBoardSize};
if (game->isSecond)
OffsetRect(&gameWindowBounds, kBoardSize + 16 + kBugspace, 0);
game->wind = (CWindowPtr) NewCWindow(0L, &gameWindowBounds, gScratch, false, documentProc, (WindowPtr) -1L, true, 0);
verify(game->wind);
// remember location of window from last time
if (game->isFirst && !EmptyRect(&gPrefs.gameWindPos1))
MoveWindow((WindowPtr) game->wind, gPrefs.gameWindPos1.left, gPrefs.gameWindPos1.top, false);
else if (game->isSecond && !EmptyRect(&gPrefs.gameWindPos2))
MoveWindow((WindowPtr) game->wind, gPrefs.gameWindPos2.left, gPrefs.gameWindPos2.top, false);
ShowWindow((WindowPtr) game->wind);
strncpy(game->name[0], p1, 127); game->name[0][127] = 0;
strncpy(game->name[1], p2, 127); game->name[1][127] = 0;
memcpy(game->board, initialPosition, sizeof(Board));
game->number = gameNum;
game->origNumber = gameNum;
game->jexiste = true;
game->relation = RELATION_OBSERVING_PLAYED;
game->gameMins = 0;
game->gameInc = 0;
game->elapsed[0] = 0;
// bughouse stuff
game->bug = false;
short nnn, mmm;
for (mmm=0;mmm<2;mmm++)
for (nnn=0;nnn<5;nnn++)
game->reserves[mmm][nnn] = 0;
// examining stuff
for (nnn=0;nnn<kNumGameControls;nnn++)
game->ctl[nnn] = 0;
game->footer = false;
game->setup = false;
game->turn = kWhite;
game->ptime[0] = 0;
game->ptime[1] = 0;
game->thinking = 0;
game->strength[0] = 0; game->strength[1] = 0;
game->flip = flip;
game->next = gGames;
if (game->next)
game->next->prev = game;
game->prev = nil;
gGames = game;
game->lastMove[0][0] = -1; game->lastMove[0][1] = 0;
game->lastMove[1][0] = 0; game->lastMove[1][1] = 0;
game->tempDest.h = -1;
game->p1OffsetY = kHeader;
game->bOffsetY = kStatY + game->p1OffsetY;
game->p2OffsetY = game->bOffsetY + kBoardSize;
SetRect(&game->boardRect, 0, game->bOffsetY, kBoardSize, game->bOffsetY + kBoardSize);
game->sqsize = 32;
game->lmove[0][0] = 0;
game->lmove[1][0] = 0;
game->officialMove = 1;
game->endReason[0] = 0;
// check for default sizes
if (game->isFirst && gPrefs.boardSize1 != game->boardRect.right)
SetGameWindowSize(game, gPrefs.boardSize1 - game->boardRect.right);
if (game->isSecond && gPrefs.boardSize2 != game->boardRect.right)
SetGameWindowSize(game, gPrefs.boardSize2 - game->boardRect.right);
return game;
}
// k = any keyboard scan code, 0-127
static int isPressed(unsigned short k )
{
return ( ( km[k>>3] >> (k & 7) ) & 1);
}
static void
ShowLastMove(void)
{
// draw a line where the last move occurred
WindowPtr win = FrontWindow();
if (!win)
return;
Game *game = FindGameFromWindow(win);
if (!game)
return;
if (game->lastMove[0][0] < 0)
return; // no move yet
SetGWorld(game->wind, maindev);
RGBColor col = {0xFFFF, 0, 0};
RGBForeColor(&col);
short siz = game->sqsize;
PenSize(4, 4);
if (game->lastMove[0][0] == game->lastMove[1][0] && game->lastMove[0][1] == game->lastMove[1][1])
PenSize(8, 8); // make more clear in bughouse
if (!game->flip) {
MoveTo(game->lastMove[0][0] * siz + (siz >> 1) - 2, (7 - game->lastMove[0][1]) * siz + (siz >> 1) - 2 + game->bOffsetY);
LineTo(game->lastMove[1][0] * siz + (siz >> 1) - 2, (7 - game->lastMove[1][1]) * siz + (siz >> 1) - 2 + game->bOffsetY);
}
else {
MoveTo(((7-game->lastMove[0][0]) * siz + (siz >> 1) - 2), (game->lastMove[0][1]) * siz + (siz >> 1) - 2 + game->bOffsetY);
LineTo(((7-game->lastMove[1][0]) * siz + (siz >> 1) - 2), (game->lastMove[1][1]) * siz + (siz >> 1) - 2 + game->bOffsetY);
}
while (isPressed(optionkey)) {GetKeys((UInt32 *) km);}
PenNormal();
RGBForeColor(&rgbBlack);
DrawGameBoard(game);
}
static void
CheckTimes(void)
{
ulong myTime = TickCount();
Game *game = gGames;
while (game) {
if (game->jexiste && game->turn >= 0
&& game->relation != RELATION_EXAMINING
&& game->relation != RELATION_ISOLATED_BOARD
&& game->relation != RELATION_OBSERVING_STATIC) {
ulong d = myTime - game->lTime;
short ds = d / 60;
if (ds > 0) {
game->lTime += ds * 60;
short ot = game->ptime[game->turn];
game->ptime[game->turn] -= ds;
short nt = game->ptime[game->turn];
if (game->relation == RELATION_PLAYING_NOTMYMOVE &&
gPrefs.autoFlag && ot > 0 && nt <= 0) {
// let's flag their asses
bprintf("flag\n");
tprintf("(Flagging opponent.)\r");
}
#if TIMESTAMP
// check time for timestamp
if (!gSentAlarm && gPrefs.timeseal && gPrefs.serverType == kIcc &&
game->relation == RELATION_PLAYING_MYMOVE &&
nt < 0) {
// let's tell server dudes
send_alarm();
gSentAlarm = true;
}
#endif
// we also keep track of how long they've been thinking
game->thinking += ds;
DrawGameStats(game);
DrawGameHeader(game);
}
}
game = game->next;
verify(game != gGames);
}
}
static void DragPiece2(void);
void
GameIdle(void)
{
if (!gPlaying)
return; // that would be bad
curTime = TickCount();
GetKeys((UInt32 *) km);
if (isPressed(optionkey))
ShowLastMove();
// adjust time
CheckTimes();
DragPiece2();
}
static void
Point2Square(Game *game, Point *pt)
{
pt->v -= game->bOffsetY;
if (pt->v < 0) {
pt->h = -2;
return;
}
pt->h /= game->sqsize; pt->v /= game->sqsize;
if (pt->h < 0 || pt->v < 0 || pt->h > 7 || pt->v > 7) {
pt->h = -2;
return; // out of range
}
if (!game->flip)
pt->v = 7 - pt->v;
else
pt->h = 7 - pt->h;
}
static void
DrawBoardSection(Game *game, Rect *r)
{
Rect rr = *r;
rr.right++; rr.bottom++;
if (rr.right % kSquareSize) rr.right += kSquareSize - rr.right % kSquareSize;
if (rr.bottom % kSquareSize) rr.bottom += kSquareSize - rr.bottom % kSquareSize;
if (rr.right > kBoardSize) rr.right = kBoardSize;
if (rr.bottom > kBoardSize) rr.bottom = kBoardSize;
rr.left -= rr.left % kSquareSize;
rr.top -= rr.top % kSquareSize;
Rect dest = rr;
// offset due to scaling
dest.left = (dest.left * game->sqsize) / kSquareSize;
dest.top = (dest.top * game->sqsize) / kSquareSize;
dest.right = (dest.right * game->sqsize) / kSquareSize;
dest.bottom = (dest.bottom * game->sqsize) / kSquareSize;
OffsetRect(&dest, game->boardRect.left, game->boardRect.top);
CopyBits((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
&rr, &dest, srcCopy, nil);
}
static Point
DragPiece(Game *game, short pc, short offx, short offy, Point origin)
{
Fastmap *fm = Piece2Fastmap(pc);
verify(fm);
Point ms, sq;
Boolean inSquare;
short siz = game->sqsize;
GetMouse(&ms); ms.v -= game->bOffsetY;
HideCursor();
Rect dirty = {0,0,0,0};
if (origin.h >= 0) {
if (!game->flip)
dirty.left = origin.h * kSquareSize;
else
dirty.left = (7-origin.h) * kSquareSize;
dirty.right = dirty.left + kSquareSize;
if (!game->flip)
dirty.top = (7 - origin.v) * kSquareSize;
else
dirty.top = origin.v * kSquareSize;
dirty.bottom = dirty.top + kSquareSize;
}
do {
CheckTimes();
SetGWorld(boff, nil);
DrawBoard(game->board, game);
// draw the piece we're dragging
SetGWorld(game->wind, maindev);
GetMouse(&ms);
ms.v -= offy + game->bOffsetY; ms.h -= offx;
// find square we're in
inSquare = false;
sq = ms;
sq.h += siz / 2;
sq.v += siz / 2;
if ((sq.h % siz > 4) && (sq.h % siz < siz - 4)
&& (sq.v % siz > 4) && (sq.v % siz < siz - 4)) {
sq.v += game->bOffsetY; // ugly, silly, but heck
Point2Square(game, &sq);
inSquare = sq.h >= 0;
}
else {
// some extra work to see if they dragged it completely off the board
// in that case, we return -2 (for setup)
sq.v += game->bOffsetY; // ugly, silly, but heck
Point2Square(game, &sq);
if (sq.h >= 0)
sq.h = -1;
}
SetGWorld(boff, nil);
// draw target
Rect rr = {0,0,0,0};
if (inSquare && !EqualPt(origin, sq)) {
if (!game->flip)
rr.left = sq.h * kSquareSize;
else
rr.left = (7-sq.h) * kSquareSize;
rr.right = rr.left + kSquareSize;
if (!game->flip)
rr.top = (7 - sq.v) * kSquareSize;
else
rr.top = sq.v * kSquareSize;
rr.bottom = rr.top + kSquareSize;
InsetRect(&rr, 4, 4);
RGBColor col = {0xFFFF, 0, 0};
RGBForeColor(&col);
MoveTo(rr.left, rr.top);
LineTo(rr.right, rr.bottom);
MoveTo(rr.right, rr.top);
LineTo(rr.left, rr.bottom);
RGBForeColor(&rgbBlack);
rr.right++; rr.bottom++;
if (dirty.right > 0 && dirty.bottom > 0)
UnionRect(&rr, &dirty, &dirty);
else
dirty = rr; // first time through loop
}
// draw piece we're sliding around
Rect rec = {0, 0, 32, 32};
ms.h = (float) ms.h * 32.0 / (float) siz;
ms.v = (float) ms.v * 32.0 / (float) siz;
OffsetRect(&rec, ms.h, ms.v);
fm->DrawMask(boff, &rec);
if (dirty.right > 0 && dirty.bottom > 0)
UnionRect(&rec, &dirty, &dirty);
else
dirty = rec;
SetGWorld(game->wind, maindev);
if (dirty.left < 0) dirty.left = 0;
if (dirty.top < 0) dirty.top = 0;
if (dirty.bottom > kBoardSize) dirty.bottom = kBoardSize;
if (dirty.right > kBoardSize) dirty.right = kBoardSize;
DrawBoardSection(game, &dirty);
// Rect dest = dirty;
// OffsetRect(&dest, game->boardRect.left, game->boardRect.top);
// CopyBits((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
// &boffrect, &game->boardRect, srcCopy, nil);
// CopyBits((BitMap *) *(boff->portPixMap), (BitMap *) *(game->wind->portPixMap),
// &dirty, &dest, srcCopy, nil);
// prepare dirty for next loop
dirty = rec;
if (rr.right > 0)
UnionRect(&rr, &dirty, &dirty);
} while (Button());
ShowCursor();
return sq;
}
static char
Piece2Char(short pc)
{
// black in capitals
switch(pc) {
case WhitePawn: return 'P'; case BlackPawn: return 'p';
case WhiteKnight: return 'N'; case BlackKnight: return 'n';
case WhiteBishop: return 'B'; case BlackBishop: return 'b';
case WhiteRook: return 'R'; case BlackRook: return 'r';
case WhiteQueen: return 'Q'; case BlackQueen: return 'q';
case WhiteKing: return 'K'; case BlackKing: return 'k';
default: return '?';
}
}
static void
HandleBugClick(Game *game, Point p)
{
short pc;
short plr;
if (p.v > kBugY + kBugPadding) {
if (p.v > kBugY * 2 + kBugPadding)
return;
if (!game->flip) {
pc = WhitePawn + (p.v - (kBugY + kBugPadding)) / kBugsize;
plr = kWhite;
}
else {
pc = BlackPawn + (p.v - (kBugY + kBugPadding)) / kBugsize;
plr = kBlack;
}
}
else if (p.v < kBugY) {
if (!game->flip) {
pc = BlackPawn + p.v / kBugsize;
plr = kBlack;
}
else {
pc = WhitePawn + p.v / kBugsize;
plr = kWhite;
}
}
else
return;
if (pc < WhitePawn || pc > BlackKing)
return;
if (Piece2Player(pc) != game->turn && !game->setup)
return; // wrong color piece
Point pt = {-1, -1};
short offs;
if (!game->flip)
offs = plr == kWhite ? 16 : -16;
else
offs = plr == kBlack ? 16 : -16;
Point dest = DragPiece(game, pc, kBugspace + 8, 16 + offs, pt);
if (dest.h < 0) {
DrawGameBoard(game);
return;
}
game->board[dest.h][dest.v] = pc;
DrawGameBoard(game);
game->tempDest = dest;
// now deal with the move
char ch = '?';
ch = Piece2Char(pc);
bprintf("%c@%c%c\n", ch, 'a' + dest.h, '1' + dest.v);
// tprintf("%c@%c%c\n", ch, 'a' + dest.h, '1' + dest.v);
}
static void
DoFooterClick(Game *game, Point *pt)
{
ControlHandle ch = nil;
// let's see if they hit a button
if (FindControl(*pt, (WindowPtr) game->wind, &ch))
if (TrackControl(ch, *pt, nil)) {
long id = GetCRefCon(ch);
switch (id) {
case ctlBack: bprintf("backward\n"); break;
case ctlForward: bprintf("forward\n"); break;
case ctlStart: bprintf("backward 999\n"); break;
case ctlEnd: bprintf("forward 999\n"); break;
case ctlRevert: bprintf("revert\n"); break;
default: break;
}
}
}
static void
EndMove(void)
{
if (gClickType != kNoMove) {
verify(gDragGame);
Game *game = gDragGame;
if (gClickType == kMove) {
if (EqualPt(gDestPoint, gOrigPoint)) // not a move
gDestPoint.h = -1;
if (gDestPoint.h < 0)
game->board[gOrigPoint.h][gOrigPoint.v] = gOldPiece;
else
game->board[gDestPoint.h][gDestPoint.v] = gOldPiece;
if (gDestPoint.h >= 0)
game->tempDest = gDestPoint;
else
game->tempDest.h = -1;
DrawGameBoard(game);
// now deal with the move
if (gDestPoint.h >= 0) {
bprintf("%c%c%c%c\n", 'a' + gOrigPoint.h, '1' + gOrigPoint.v, 'a' + gDestPoint.h, '1' + gDestPoint.v);
// tprintf("%c%c%c%c\r", 'a' + gOrigPoint.h, '1' + gOrigPoint.v, 'a' + gDestPoint.h, '1' + gDestPoint.v);
// tprintf("%d %d\r", gDestPoint.h, gDestPoint.v);
}
}
else if (gClickType == kSetupMove) {
if (EqualPt(gDestPoint, gOrigPoint)) // not a move
gDestPoint.h = -1;
if (gDestPoint.h < 0)
game->board[gOrigPoint.h][gOrigPoint.v] = gOldPiece;
else
game->board[gDestPoint.h][gDestPoint.v] = gOldPiece;
if (gDestPoint.h >= 0)
game->tempDest = gDestPoint;
else
game->tempDest.h = -1;
DrawGameBoard(game);
// now deal with the move
if (gDestPoint.h >= 0) {
// we're in setup mode, and they're moving a piece
// this isn't supported in server, but why not here? just clear and place
bprintf("x@%c%c\n", 'a' + gOrigPoint.h, '1' + gOrigPoint.v); // clear old piece
bprintf("%c@%c%c\n", Piece2Char(gOldPiece), 'a' + gDestPoint.h, '1' + gDestPoint.v);
}
else if (gDestPoint.h == -2) {
// we're in setup mode, and they're clearing a piece off the board
bprintf("x@%c%c\n", 'a' + gOrigPoint.h, '1' + gOrigPoint.v);
game->board[gOrigPoint.h][gOrigPoint.v] = empty;
DrawGameBoard(game);
}
}
else if (gClickType == kBugMove) {
if (gDestPoint.h < 0)
DrawGameBoard(game);
else {
game->board[gDestPoint.h][gDestPoint.v] = gOldPiece;
DrawGameBoard(game);
game->tempDest = gDestPoint;
// now deal with the move
char ch = '?';
ch = Piece2Char(gOldPiece);
bprintf("%c@%c%c\n", ch, 'a' + gDestPoint.h, '1' + gDestPoint.v);
// tprintf("%c@%c%c\n", ch, 'a' + gDestPoint.h, '1' + gDestPoint.v);
}
}
}
gClickType = kNoMove;
ShowCursor();
}
static void
StartDrag(void)
{
Point origin = gOrigPoint;
HideCursor();
SetRect(&dirty, 0, 0, 0, 0);
gDestPoint.h = -2;
gDestPoint.v = -2;
if (origin.h >= 0) {
if (!gDragGame->flip)
dirty.left = origin.h * kSquareSize;
else
dirty.left = (7-origin.h) * kSquareSize;
dirty.right = dirty.left + kSquareSize;
if (!gDragGame->flip)
dirty.top = (7 - origin.v) * kSquareSize;
else
dirty.top = origin.v * kSquareSize;
dirty.bottom = dirty.top + kSquareSize;
}
}
// if we're dragging when we get a server update, make sure the source remains empty
void
GotBoardFromServer(Game *game)
{
if (gClickType == kNoMove || game != gDragGame)
return;
if (gOrigPoint.h < 0)
return; // a place
game->board[gOrigPoint.h][gOrigPoint.v] = empty;
}
static void
HandleBugClick2(Game *game, Point p)
{
short pc;
short plr;
if (p.v > kBugY + kBugPadding) {
if (p.v > kBugY * 2 + kBugPadding)
return;
if (!game->flip) {
pc = WhitePawn + (p.v - (kBugY + kBugPadding)) / kBugsize;
plr = kWhite;
}
else {
pc = BlackPawn + (p.v - (kBugY + kBugPadding)) / kBugsize;
plr = kBlack;
}
}
else if (p.v < kBugY) {
if (!game->flip) {
pc = BlackPawn + p.v / kBugsize;
plr = kBlack;
}
else {
pc = WhitePawn + p.v / kBugsize;
plr = kWhite;
}
}
else
return;
if (pc < WhitePawn || pc > BlackKing)
return;
if ((Piece2Player(pc) != (game->turn ^ (game->relation == RELATION_PLAYING_NOTMYMOVE))) && !game->setup)
return; // wrong color piece
Point pt = {-1, -1};
short offs;
if (!game->flip)
offs = plr == kWhite ? 16 : -16;
else
offs = plr == kBlack ? 16 : -16;
gOrigPoint = pt;
gOldPiece = pc;
gDragGame = game;
offx = kBugspace + 8;
offy = 16 + offs;
gClickType = kBugMove;
StartDrag();
DragPiece2();
}
static void
DragPiece2(void)
{
Game *game = gDragGame;
if (!game || gClickType == kNoMove)
return;
Fastmap *fm = Piece2Fastmap(gOldPiece);
verify(fm);
Point ms, sq;
Boolean inSquare;
short siz = game->sqsize;
Point origin = gOrigPoint;
ulong stTime = TickCount();
sq = gDestPoint;
if (Button())
do {
SetGWorld(boff, nil);
DrawBoard(game->board, game);
// draw the piece we're dragging
SetGWorld(game->wind, maindev);
GetMouse(&ms);
ms.v -= offy + game->bOffsetY; ms.h -= offx;
// find square we're in
inSquare = false;
sq = ms;
sq.h += siz / 2;
sq.v += siz / 2;
if ((sq.h % siz > 4) && (sq.h % siz < siz - 4)
&& (sq.v % siz > 4) && (sq.v % siz < siz - 4)) {
sq.v += game->bOffsetY; // ugly, silly, but heck
Point2Square(game, &sq);
inSquare = sq.h >= 0;
}
else {
// some extra work to see if they dragged it completely off the board
// in that case, we return -2 (for setup)
sq.v += game->bOffsetY; // ugly, silly, but heck
Point2Square(game, &sq);
if (sq.h >= 0)
sq.h = -1;
}
SetGWorld(boff, nil);
// draw target
Rect rr = {0,0,0,0};
if (inSquare && !EqualPt(origin, sq)) {
if (!game->flip)
rr.left = sq.h * kSquareSize;
else
rr.left = (7-sq.h) * kSquareSize;
rr.right = rr.left + kSquareSize;
if (!game->flip)
rr.top = (7 - sq.v) * kSquareSize;
else
rr.top = sq.v * kSquareSize;
rr.bottom = rr.top + kSquareSize;
InsetRect(&rr, 4, 4);
RGBColor col = {0xFFFF, 0, 0};
RGBForeColor(&col);
MoveTo(rr.left, rr.top);
LineTo(rr.right, rr.bottom);
MoveTo(rr.right, rr.top);
LineTo(rr.left, rr.bottom);
RGBForeColor(&rgbBlack);
rr.right++; rr.bottom++;
if (dirty.right > 0 && dirty.bottom > 0)
UnionRect(&rr, &dirty, &dirty);
else
dirty = rr; // first time through loop
}
// draw piece we're sliding around
Rect rec = {0, 0, 32, 32};
ms.h = (float) ms.h * 32.0 / (float) siz;
ms.v = (float) ms.v * 32.0 / (float) siz;
OffsetRect(&rec, ms.h, ms.v);
fm->DrawMask(boff, &rec);
if (dirty.right > 0 && dirty.bottom > 0)
UnionRect(&rec, &dirty, &dirty);
else
dirty = rec;
SetGWorld(game->wind, maindev);
if (dirty.left < 0) dirty.left = 0;
if (dirty.top < 0) dirty.top = 0;
if (dirty.bottom > kBoardSize) dirty.bottom = kBoardSize;
if (dirty.right > kBoardSize) dirty.right = kBoardSize;
DrawBoardSection(game, &dirty);
// prepare dirty for next loop
dirty = rec;
if (rr.right > 0)
UnionRect(&rr, &dirty, &dirty);
} while (Button() && (TickCount() - stTime < 20));
gDestPoint = sq;
if (!Button()) {
EndMove();
}
}
// pick up a piece and move it
void
HandleGameClick(Point *pt)
{
Point p = *pt;
Game *game = FindGameFromWindow(FrontWindow());
if (!game) return;
// check for growth
// short mx = game->wind->portRect.
if (gClickType != kNoMove)
EndMove(); // shouldn't happen much, but . . .
if (game->footer && pt->v >= kWinHeight)
DoFooterClick(game, pt);
// check to see if dragging pieces is valid for this board
if (game->relation <= 0 && game->relation != RELATION_PLAYING_NOTMYMOVE)
return; // nope
if (p.h > game->boardRect.right) {
HandleBugClick2(game, p);
return;
}
// find board coords
Point2Square(game, &p);
if (p.h < 0)
return; // out of range
short oldPiece = game->board[p.h][p.v];
if (oldPiece == empty)
return;
// if (Piece2Player(oldPiece) != game->turn && !game->setup)
// return; // wrong color piece
if (game->relation == RELATION_PLAYING_MYMOVE) {
if (game->turn == kWhite && oldPiece >= BlackPawn)
return; // wrong kind of piece
if (game->turn == kBlack && oldPiece <= WhiteKing)
return; // wrong kind of piece
}
else if (game->relation == RELATION_PLAYING_NOTMYMOVE) {
if (game->turn == kWhite && oldPiece <= WhiteKing)
return; // wrong kind of piece
if (game->turn == kBlack && oldPiece >= BlackPawn)
return; // wrong kind of piece
}
game->board[p.h][p.v] = empty;
// DrawGameBoard(game);
gOrigPoint = p;
gOldPiece = oldPiece;
gDragGame = game;
offx = pt->h % game->sqsize;
offy = (pt->v - game->bOffsetY) % game->sqsize;
gClickType = kMove;
if (game->setup)
gClickType = kSetupMove;
StartDrag();
DragPiece2();
/*
if (EqualPt(dest, p)) // not a move
dest.h = -1;
if (dest.h < 0)
game->board[p.h][p.v] = oldPiece;
else
game->board[dest.h][dest.v] = oldPiece;
game->tempDest = dest;
if (!(dest.h == -2 && game->setup))
DrawGameBoard(game);
// now deal with the move
if (dest.h < 0) {
if (dest.h == -2 && game->setup) {
// we're in setup mode, and they're clearing a piece off the board
bprintf("x@%c%c\n", 'a' + p.h, '1' + p.v);
game->board[p.h][p.v] = empty;
DrawGameBoard(game);
}
return;
}
if (game->setup) {
// we're in setup mode, and they're moving a piece
// this isn't supported in server, but why not here? just clear and place
bprintf("x@%c%c\n", 'a' + p.h, '1' + p.v); // clear old piece
bprintf("%c@%c%c\n", Piece2Char(oldPiece), 'a' + dest.h, '1' + dest.v);
}
else
bprintf("%c%c%c%c\n", 'a' + p.h, '1' + p.v, 'a' + dest.h, '1' + dest.v);
*/
}